home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / msdos / lynx / source / www / library / implemen / htaautil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-25  |  15.6 KB  |  573 lines

  1.  
  2. /* MODULE                            HTAAUtil.c
  3. **        COMMON PARTS OF ACCESS AUTHORIZATION MODULE
  4. **            FOR BOTH SERVER AND BROWSER
  5. **
  6. ** IMPORTANT:
  7. **    Routines in this module use dynamic allocation, but free
  8. **    automatically all the memory reserved by them.
  9. **
  10. **    Therefore the caller never has to (and never should)
  11. **    free() any object returned by these functions.
  12. **
  13. **    Therefore also all the strings returned by this package
  14. **    are only valid until the next call to the same function
  15. **    is made. This approach is selected, because of the nature
  16. **    of access authorization: no string returned by the package
  17. **    needs to be valid longer than until the next call.
  18. **
  19. **    This also makes it easy to plug the AA package in:
  20. **    you don't have to ponder whether to free() something
  21. **    here or is it done somewhere else (because it is always
  22. **    done somewhere else).
  23. **
  24. **    The strings that the package needs to store are copied
  25. **    so the original strings given as parameters to AA
  26. **    functions may be freed or modified with no side effects.
  27. **
  28. **    The AA package does not free() anything else than what
  29. **    it has itself allocated.
  30. **
  31. **    AA (Access Authorization) package means modules which
  32. **    names start with HTAA.
  33. **
  34. ** AUTHORS:
  35. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  36. **    MD     Mark Donszelmann    duns@vxdeop.cern.ch
  37. **
  38. ** HISTORY:
  39. **     8 Nov 93  MD    (VMS only) Added case insensitive comparison in HTAA_templateCaseMatch
  40. **
  41. **
  42. ** BUGS:
  43. **
  44. **
  45. */
  46. #include"capalloc.h"
  47. #include"capstdio.h"
  48. #include <string.h>
  49. #include "HTUtils.h"
  50. #include "tcp.h"    /* NETREAD() etc.    */
  51. #include "HTAAUtil.h"    /* Implemented here    */
  52. #include "HTAssoc.h"    /* Assoc list        */
  53.  
  54.  
  55. /* PUBLIC                        HTAAScheme_enum()
  56. **        TRANSLATE SCHEME NAME INTO
  57. **        A SCHEME ENUMERATION
  58. **
  59. ** ON ENTRY:
  60. **    name        is a string representing the scheme name.
  61. **
  62. ** ON EXIT:
  63. **    returns        the enumerated constant for that scheme.
  64. */
  65. PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
  66. {
  67.     static char *upcased = NULL;
  68.     char *cur;
  69.  
  70.     if (!name) return HTAA_UNKNOWN;
  71.  
  72.     StrAllocCopy(upcased, name);
  73.     cur = upcased;
  74.     while (*cur) {
  75.     *cur = TOUPPER(*cur);
  76.     cur++;
  77.     }
  78.     
  79.     if (!strncmp(upcased, "NONE", 4))
  80.     return HTAA_NONE;
  81.     else if (!strncmp(upcased, "BASIC", 5))
  82.     return HTAA_BASIC;
  83.     else if (!strncmp(upcased, "PUBKEY", 6))
  84.     return HTAA_PUBKEY;
  85.     else if (!strncmp(upcased, "KERBEROSV4", 10))
  86.     return HTAA_KERBEROS_V4;
  87.     else if (!strncmp(upcased, "KERBEROSV5", 10))
  88.     return HTAA_KERBEROS_V5;
  89.     else
  90.     return HTAA_UNKNOWN;
  91. }
  92.  
  93.  
  94. /* PUBLIC                        HTAAScheme_name()
  95. **            GET THE NAME OF A GIVEN SCHEME
  96. ** ON ENTRY:
  97. **    scheme        is one of the scheme enum values:
  98. **            HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
  99. **
  100. ** ON EXIT:
  101. **    returns        the name of the scheme, i.e.
  102. **            "None", "Basic", "Pubkey", ...
  103. */
  104. PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
  105. {
  106.     switch (scheme) {
  107.       case HTAA_NONE:        return "None";          break;
  108.       case HTAA_BASIC:        return "Basic";         break;
  109.       case HTAA_PUBKEY:        return "Pubkey";        break;
  110.       case HTAA_KERBEROS_V4:    return "KerberosV4";    break;
  111.       case HTAA_KERBEROS_V5:    return "KerberosV5";    break;
  112.       case HTAA_UNKNOWN:    return "UNKNOWN";       break;
  113.       default:            return "THIS-IS-A-BUG";
  114.     }
  115. }
  116.  
  117.  
  118. /* PUBLIC                            HTAAMethod_enum()
  119. **        TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE
  120. ** ON ENTRY:
  121. **    name        is the method name to translate.
  122. **
  123. ** ON EXIT:
  124. **    returns        HTAAMethod enumerated value corresponding
  125. **            to the given name.
  126. */
  127. PUBLIC HTAAMethod HTAAMethod_enum ARGS1(CONST char *, name)
  128. {
  129.     char tmp[MAX_METHODNAME_LEN+1];
  130.     CONST char *src = name;
  131.     char *dest = tmp;
  132.  
  133.     if (!name) return METHOD_UNKNOWN;
  134.  
  135.     while (*src) {
  136.     *dest = TOUPPER(*src);
  137.     dest++;
  138.     src++;
  139.     }
  140.     *dest = 0;
  141.  
  142.     if (0==strcmp(tmp, "GET"))
  143.     return METHOD_GET;
  144.     else if (0==strcmp(tmp, "PUT"))
  145.     return METHOD_PUT;
  146.     else
  147.     return METHOD_UNKNOWN;
  148. }
  149.  
  150.  
  151. /* PUBLIC                        HTAAMethod_name()
  152. **            GET THE NAME OF A GIVEN METHOD
  153. ** ON ENTRY:
  154. **    method        is one of the method enum values:
  155. **            METHOD_GET, METHOD_PUT, ...
  156. **
  157. ** ON EXIT:
  158. **    returns        the name of the scheme, i.e.
  159. **            "GET", "PUT", ...
  160. */
  161. PUBLIC char *HTAAMethod_name ARGS1(HTAAMethod, method)
  162. {
  163.     switch (method) {
  164.       case METHOD_GET:        return "GET";           break;
  165.       case METHOD_PUT:        return "PUT";           break;
  166.       case METHOD_UNKNOWN:    return "UNKNOWN";       break;
  167.       default:            return "THIS-IS-A-BUG";
  168.     }
  169. }
  170.  
  171.  
  172. /* PUBLIC                        HTAAMethod_inList()
  173. **        IS A METHOD IN A LIST OF METHOD NAMES
  174. ** ON ENTRY:
  175. **    method        is the method to look for.
  176. **    list        is a list of method names.
  177. **
  178. ** ON EXIT:
  179. **    returns        YES, if method was found.
  180. **            NO, if not found.
  181. */
  182. PUBLIC BOOL HTAAMethod_inList ARGS2(HTAAMethod,    method,
  183.                     HTList *,    list)
  184. {
  185.     HTList *cur = list;
  186.     char *item;
  187.  
  188.     while (NULL != (item = (char*)HTList_nextObject(cur))) {
  189. #ifndef RELEASE
  190.     if (TRACE) fprintf(stderr, " %s", item);
  191. #endif /* RELEASE */
  192.     if (method == HTAAMethod_enum(item))
  193.         return YES;
  194.     }
  195.  
  196.     return NO;    /* Not found */
  197. }
  198.  
  199.  
  200.  
  201. /* PUBLIC                        HTAA_templateMatch()
  202. **        STRING COMPARISON FUNCTION FOR FILE NAMES
  203. **           WITH ONE WILDCARD * IN THE TEMPLATE
  204. ** NOTE:
  205. **    This is essentially the same code as in HTRules.c, but it
  206. **    cannot be used because it is embedded in between other code.
  207. **    (In fact, HTRules.c should use this routine, but then this
  208. **     routine would have to be more sophisticated... why is life
  209. **     sometimes so hard...)
  210. **
  211. ** ON ENTRY:
  212. **    template    is a template string to match the file name
  213. **            agaist, may contain a single wildcard
  214. **            character * which matches zero or more
  215. **            arbitrary characters.
  216. **    filename    is the filename (or pathname) to be matched
  217. **            agaist the template.
  218. **
  219. ** ON EXIT:
  220. **    returns        YES, if filename matches the template.
  221. **            NO, otherwise.
  222. */
  223. PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template, 
  224.                      CONST char *, filename)
  225. {
  226.     CONST char *p = template;
  227.     CONST char *q = filename;
  228.     int m;
  229.  
  230.     for( ; *p  &&  *q  &&  *p == *q; p++, q++)    /* Find first mismatch */
  231.     ; /* do nothing else */
  232.  
  233.     if (!*p && !*q)    return YES;    /* Equally long equal strings */
  234.     else if ('*' == *p) {        /* Wildcard */
  235.     p++;                /* Skip wildcard character */
  236.     m = strlen(q) - strlen(p);    /* Amount to match to wildcard */
  237.     if (m < 0) return NO;        /* No match, filename too short */
  238.     else {            /* Skip the matched characters and compare */
  239.         if (strcmp(p, q+m))    return NO;    /* Tail mismatch */
  240.         else                return YES;    /* Tail match */
  241.     }
  242.     }    /* if wildcard */
  243.     else        return NO;    /* Length or character mismatch */
  244. }    
  245.  
  246.  
  247. /* PUBLIC                        HTAA_templateCaseMatch()
  248. **        STRING COMPARISON FUNCTION FOR FILE NAMES
  249. **           WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
  250. ** NOTE:
  251. **    This is essentially the same code as in HTAA_templateMatch, but
  252. **    it compares case insensitive (for VMS). Reason for this routine
  253. **    is that HTAA_templateMatch gets called from several places, also 
  254. **    there where a case sensitive match is needed, so one cannot just
  255. **    change the HTAA_templateMatch routine for VMS.
  256. **
  257. ** ON ENTRY:
  258. **    template    is a template string to match the file name
  259. **            agaist, may contain a single wildcard
  260. **            character * which matches zero or more
  261. **            arbitrary characters.
  262. **    filename    is the filename (or pathname) to be matched
  263. **            agaist the template.
  264. **
  265. ** ON EXIT:
  266. **    returns        YES, if filename matches the template.
  267. **            NO, otherwise.
  268. */
  269. PUBLIC BOOL HTAA_templateCaseMatch ARGS2(CONST char *, template, 
  270.                          CONST char *, filename)
  271. {
  272.     CONST char *p = template;
  273.     CONST char *q = filename;
  274.     int m;
  275.  
  276.     for( ; *p  &&  *q  &&  toupper(*p) == toupper(*q); p++, q++) /* Find first mismatch */
  277.     ; /* do nothing else */
  278.  
  279.     if (!*p && !*q)    return YES;    /* Equally long equal strings */
  280.     else if ('*' == *p) {        /* Wildcard */
  281.     p++;                /* Skip wildcard character */
  282.     m = strlen(q) - strlen(p);    /* Amount to match to wildcard */
  283.     if (m < 0) return NO;        /* No match, filename too short */
  284.     else {            /* Skip the matched characters and compare */
  285.         if (strcasecomp(p, q+m))    return NO;    /* Tail mismatch */
  286.         else                return YES;    /* Tail match */
  287.     }
  288.     }    /* if wildcard */
  289.     else        return NO;    /* Length or character mismatch */
  290. }    
  291.  
  292.  
  293. /* PUBLIC                    HTAA_makeProtectionTemplate()
  294. **        CREATE A PROTECTION TEMPLATE FOR THE FILES
  295. **        IN THE SAME DIRECTORY AS THE GIVEN FILE
  296. **        (Used by server if there is no fancier way for
  297. **        it to tell the client, and by browser if server
  298. **        didn't send WWW-ProtectionTemplate: field)
  299. ** ON ENTRY:
  300. **    docname    is the document pathname (from URL).
  301. **
  302. ** ON EXIT:
  303. **    returns    a template matching docname, and other files
  304. **        files in that directory.
  305. **
  306. **        E.g.  /foo/bar/x.html  =>  /foo/bar/ *
  307. **                            ^
  308. **                Space only to prevent it from
  309. **                being a comment marker here,
  310. **                there really isn't any space.
  311. */
  312. PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
  313. {
  314.     char *template = NULL;
  315.     char *slash = NULL;
  316.  
  317.     if (docname) {
  318.     StrAllocCopy(template, docname);
  319.     slash = strrchr(template, '/');
  320.     if (slash) slash++;
  321.     else slash = template;
  322.     *slash = (char)0;
  323.     StrAllocCat(template, "*");
  324.     }
  325.     else StrAllocCopy(template, "*");
  326. #ifndef RELEASE
  327.     if (TRACE) fprintf(stderr,
  328.                "make_template: made template `%s' for file `%s'\n",
  329.                template, docname);
  330. #endif /* RELEASE */
  331.  
  332.     return template;
  333. }
  334.  
  335.  
  336.  
  337.  
  338. /*
  339. ** Skip leading whitespace from *s forward
  340. */
  341. #define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
  342.  
  343. /*
  344. ** Kill trailing whitespace starting from *(s-1) backwords
  345. */
  346. #define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)=(char)0;}
  347.  
  348.  
  349. /* PUBLIC                        HTAA_parseArgList()
  350. **        PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
  351. ** ON ENTRY:
  352. **    str    is a comma-separated list:
  353. **
  354. **            item, item, item
  355. **        where
  356. **            item ::= value
  357. **                   | name=value
  358. **                   | name="value"
  359. **
  360. **        Leading and trailing whitespace is ignored
  361. **        everywhere except inside quotes, so the following
  362. **        examples are equal:
  363. **
  364. **            name=value,foo=bar
  365. **             name="value",foo="bar"
  366. **              name = value ,  foo = bar
  367. **               name = "value" ,  foo = "bar"
  368. **
  369. ** ON EXIT:
  370. **    returns    a list of name-value pairs (actually HTAssocList*).
  371. **        For items with no name, just value, the name is
  372. **        the number of order number of that item. E.g.
  373. **        "1" for the first, etc.
  374. */
  375. PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
  376. {
  377.     HTAssocList *assoc_list = HTAssocList_new();
  378.     char *cur = NULL;
  379.     char *name = NULL;
  380.     int index = 0;
  381.  
  382.     if (!str) return assoc_list;
  383.  
  384.     while (*str) {
  385.     SKIPWS(str);                /* Skip leading whitespace */
  386.     cur = str;
  387.     index++;
  388.  
  389.     while (*cur  &&  *cur != '='  &&  *cur != ',')
  390.         cur++;    /* Find end of name (or lonely value without a name) */
  391.     KILLWS(cur);    /* Kill trailing whitespace */
  392.  
  393.     if (*cur == '=') {            /* Name followed by a value */
  394.         *(cur++) = (char)0;            /* Terminate name */
  395.         StrAllocCopy(name, str);
  396.         SKIPWS(cur);            /* Skip WS leading the value */
  397.         str = cur;
  398.         if (*str == '"') {            /* Quoted value */
  399.         str++;
  400.         cur = str;
  401.         while (*cur  &&  *cur != '"') cur++;
  402.         if (*cur == '"')
  403.             *(cur++) = (char)0;    /* Terminate value */
  404.         /* else it is lacking terminating quote */
  405.         SKIPWS(cur);            /* Skip WS leading comma */
  406.         if (*cur == ',') cur++;        /* Skip separating colon */
  407.         }
  408.         else {                /* Unquoted value */
  409.         while (*cur  &&  *cur != ',') cur++;
  410.         KILLWS(cur);            /* Kill trailing whitespace */
  411.         if (*cur == ',')
  412.             *(cur++) = (char)0;
  413.         /* else *cur already NULL */
  414.         }
  415.     }
  416.     else {    /* No name, just a value */
  417.         if (*cur == ',') 
  418.         *(cur++) = (char)0;        /* Terminate value */
  419.         /* else last value on line (already terminated by NULL) */
  420.         StrAllocCopy(name, "nnn");    /* Room for item order number */
  421.         sprintf(name, "%d", index); /* Item order number for name */
  422.     }
  423.     HTAssocList_add(assoc_list, name, str);
  424.     str = cur;
  425.     } /* while *str */
  426.  
  427.     return assoc_list;
  428. }
  429.  
  430.  
  431.  
  432. /************** HEADER LINE READER -- DOES UNFOLDING *************************/
  433.  
  434. #define BUFFER_SIZE    1024
  435.  
  436. PRIVATE char buffer[BUFFER_SIZE + 1];
  437. PRIVATE char *start_pointer = buffer;
  438. PRIVATE char *end_pointer = buffer;
  439. PRIVATE int in_soc = -1;
  440.  
  441. /* PUBLIC                        HTAA_setupReader()
  442. **        SET UP HEADER LINE READER, i.e. give
  443. **        the already-read-but-not-yet-processed
  444. **        buffer of text to be read before more
  445. **        is read from the socket.
  446. ** ON ENTRY:
  447. **    start_of_headers is a pointer to a buffer containing
  448. **            the beginning of the header lines
  449. **            (rest will be read from a socket).
  450. **    length        is the number of valid characters in
  451. **            'start_of_headers' buffer.
  452. **    soc        is the socket to use when start_of_headers
  453. **            buffer is used up.
  454. ** ON EXIT:
  455. **    returns        nothing.
  456. **            Subsequent calls to HTAA_getUnfoldedLine()
  457. **            will use this buffer first and then
  458. **            proceed to read from socket.
  459. */
  460. PUBLIC void HTAA_setupReader ARGS3(char *,    start_of_headers,
  461.                    int,        length,
  462.                    int,        soc)
  463. {
  464.     start_pointer = buffer;
  465.     if (start_of_headers) {
  466.     strncpy(buffer, start_of_headers, length);
  467.     buffer[length] = (char)0;
  468.     end_pointer = buffer + length;
  469.     }
  470.     else {
  471.     *start_pointer = (char)0;
  472.     end_pointer = start_pointer;
  473.     }
  474.     in_soc = soc;
  475. }
  476.  
  477.  
  478. /* PUBLIC                        HTAA_getUnfoldedLine()
  479. **        READ AN UNFOLDED HEADER LINE FROM SOCKET
  480. ** ON ENTRY:
  481. **    HTAA_setupReader must absolutely be called before
  482. **    this function to set up internal buffer.
  483. **
  484. ** ON EXIT:
  485. **    returns    a newly-allocated character string representing
  486. **        the read line.  The line is unfolded, i.e.
  487. **        lines that begin with whitespace are appended
  488. **        to current line.  E.g.
  489. **
  490. **            Field-Name: Blaa-Blaa
  491. **             This-Is-A-Continuation-Line
  492. **             Here-Is_Another
  493. **
  494. **        is seen by the caller as:
  495. **
  496. **    Field-Name: Blaa-Blaa This-Is-A-Continuation-Line Here-Is_Another
  497. **
  498. */
  499. PUBLIC char *HTAA_getUnfoldedLine NOARGS
  500. {
  501.     char *line = NULL;
  502.     char *cur;
  503.     int count;
  504.     BOOL peek_for_folding = NO;
  505.  
  506.     if (in_soc < 0) {
  507.     fprintf(stderr, "%s %s\n",
  508.         "HTAA_getUnfoldedLine: buffer not initialized",
  509.         "with function HTAA_setupReader()");
  510.     return NULL;
  511.     }
  512.  
  513.     for(;;) {
  514.  
  515.     /* Reading from socket */
  516.  
  517.     if (start_pointer >= end_pointer) {/*Read the next block and continue*/
  518.         count = NETREAD(in_soc, buffer, BUFFER_SIZE);
  519.         if (count <= 0) {
  520.         in_soc = -1;
  521.         return line;
  522.         }
  523.         start_pointer = buffer;
  524.         end_pointer = buffer + count;
  525.         *end_pointer = (char)0;
  526. #ifdef NOT_ASCII
  527.         cur = start_pointer;
  528.         while (cur < end_pointer) {
  529.         *cur = TOASCII(*cur);
  530.         cur++;
  531.         }
  532. #endif /*NOT_ASCII*/
  533.     }
  534.     cur = start_pointer;
  535.  
  536.  
  537.     /* Unfolding */
  538.  
  539.     if (peek_for_folding) {
  540.         if (*cur != ' '  &&  *cur != '\t')
  541.         return line;    /* Ok, no continuation line */
  542.         else        /* So this is a continuation line, continue */
  543.         peek_for_folding = NO;
  544.     }
  545.  
  546.  
  547.     /* Finding end-of-line */
  548.  
  549.     while (cur < end_pointer && *cur != '\n') /* Find the end-of-line */
  550.         cur++;                  /* (or end-of-buffer).  */
  551.  
  552.     
  553.     /* Terminating line */
  554.  
  555.     if (cur < end_pointer) {    /* So *cur==LF, terminate line */
  556.         *cur = (char)0;        /* Overwrite LF */
  557.         if (*(cur-1) == '\r')
  558.         *(cur-1) = (char)0;    /* Overwrite CR */
  559.         peek_for_folding = YES;    /* Check for a continuation line */
  560.     }
  561.  
  562.  
  563.     /* Copying the result */
  564.  
  565.     if (line)
  566.         StrAllocCat(line, start_pointer);    /* Append */
  567.     else
  568.         StrAllocCopy(line, start_pointer);    /* A new line */
  569.  
  570.     start_pointer = cur+1;    /* Skip the read line */
  571.  
  572.     } /* forever */
  573. }